// DEPUIS P4
// git push https://code.google.com/p/uc-uc-uc.nxp/ master
// git pull https://uc.6969@code.google.com/p/uc-uc-uc.nxp/ master
// Modif 1
// Modif 2 depuis ex1000
// Modif 3' depuis ex1000
// modif 3 depuis p4
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
#include <NXP/crp.h>
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "PLL0setup.h"
#include "pinconfig.h"
#include "uartinfo.h"
#include "find_uart_parameters.h"
#include "udpip.h"

#define LED 0xffffffff //(1L << 22)
#define DELAY 2000000
/*
int SCSReg(void);
int RSIDReg(void); // a finir
int EXTINTReg(void);
int EXTMODEReg(void);
int EXTPOLARReg(void);
int PLL0CONReg(void);
int PLL0CFGReg(void);
int PLL0STATReg(void);
int PLL0FEEDReg(void);
int CCLKCFGReg(void);
int PCONPReg(void);
*/

// udp
void mycallback(unsigned char* msg, short len, unsigned char broadcast);
#define LONG_ARG_COMMANDE 32
char argument_commande[LONG_ARG_COMMANDE+1]; // +1 pour '\0'

// uart
void UART1_IRQHandler(void);
char *infoTxt;
char *tampon;
#define CMD_SIZE 32
char *cmd;

char *message;
volatile int debut_message = 0, fin_message= 0, message_recu = 0;
volatile int car_precedent = 0;

volatile int messageDispo, messageIndex;
volatile int impulsion = 0;

void PWM1_IRQHandler(void)
{
	printf("PWM1 INT\n");
}

int main(void)
{
    volatile static int i = 0, count = 0 ;
    infoTxt =(char*)malloc(128); // Alloue sur le Tas
    tampon = (char*)malloc(128);
    cmd = (char*)malloc(CMD_SIZE);
    // Config udp
    short idx = 1;  // 0 a 3
    unsigned short port = 54321;
    //unsigned char  mymac[6]={'l','2','3','4','5','6'};
    //unsigned char  mymac[6]={0x08,0x00,0x27,0x24,0x17,0x8a}; // pcat0137 137.138.196.188 - 08-00-27-24-17-8A
    unsigned char  mymac[6]={0x00,0x11,0x11,0x1a,0x5a,0x4b}; // pcat0137 137.138.196.188 - 00:11:11:1A:5A:4B
    //unsigned long  myip= ((137<<0)+(138<<8)+(196<<16)+(188<<24));
    unsigned long  myip= ((192<<0)+(168<<8)+(0<<16)+(9<<24));

   //NVIC_EnableIRQ(PWM1_IRQn);

    printf("Activation UDP \n");
    udpipInit(mymac, myip);
    udpipSetService(idx, port, &mycallback);
    udpipSaveRemoteForService(idx);
    udpipSetBroadcastForService(idx, port);

	messageIndex = 0;
    message = (char*)malloc(sizeof(char)*128);

    /*
    // ! Allumer l'UART AVANT d'affecter les interruptions sinon crash sur HardFault_Handler...
    // UART1 esdt normalement ON par defaut mais...
    UART1PinsEnable(); // P0.15=TXD1, P0.16=RXD1
	// INT autorisee sur UART1
	LPC_UART1->IER |= (bit0); // Int Enable Register, bit0 = Received Data Available
    NVIC_EnableIRQ(UART1_IRQn);
    printf("-> interruption UART1 activee\n");
	UART1PinsEnable(); // P0.15=TXD1, P0.16=RXD1
	set_optimal_uart_config_for_cclk(SystemCoreClock, 9600);
	UART1_SendCmd2FB755((unsigned char*)"AT+BTINFO?");
	printf("Commande envoyee.\n");
	// Toute reponse du FB755 se fait entre [13][10]....[13][10] (config usine)
	printf("Reponse FB755...\n");
  */


    LPC_SC->PCONP |= (1<<6);    			// Demarre PWM1
    LPC_SC->PCLKSEL1 &= ~((1<<13)|(1<<12));	// bit 12 & 13 a zero -> PCLK = CCLK/4
    // PWM1.6 sur pin 2.5 => PINSEL4, fonction 01 (bit11=0; bit10=1)
    LPC_PINCON->PINSEL4 &= ~(1<<11);
    LPC_PINCON->PINSEL4 |= (1<<10);
    // PWM1.5 sur pin 2.4 => PINSEL4, fonction 01 (bit11=0; bit10=1)
    LPC_PINCON->PINSEL4 &= ~(1<<9);
    LPC_PINCON->PINSEL4 |= (1<<8);

    // Si PCLK=CCLK/4=25000000, MR0=500000, MRx=37500, alors si
    // PR=0 -> T=20ms, impul=1.5ms
    // PR=1 -> T=40ms, impul=3ms
    // PR=2 -> T=60ms, impul=4.5ms
    // PR=3 -> T=80ms, impul=6ms
    // PR=9 -> T=200ms, impuls=15ms
    // PR=10-> T=220ms, impul=16.5ms
    LPC_PWM1->PR = 0;   // Prescaler
    LPC_PWM1->MCR = (1<<1); // si (1<<0) -> il faut aussi NVIC_EnableIRQ(PWM1_IRQn)
    LPC_PWM1->CTCR = 0;  // Timer mode, TC incremented when Prescaler counter = Prescale Register

    LPC_PWM1->MR0 = 500000;		// Largeur implusion
    LPC_PWM1->MR5 = 37500;  	// Duty cycle sortie 5
    LPC_PWM1->MR6 = 37500;  	// Duty cycle sortie 6
    LPC_PWM1->LER |= (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0); // rend effectives les valeurs entrees ds MRx
	// START PWM
    LPC_PWM1->PCR  = (1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9);
	LPC_PWM1->TCR |= (1<<0); // ok si aussi |(1<<3);

	while(1)
	{
     // UDP
      udpipWork();
		if ( messageDispo == 1 )
		{
		  printf("Nouvelle largeur d'impulsion = %d\n", impulsion);
		  messageDispo = 0;
          udpipSend(1, message, strlen(message));
          // Change la largeur d'implusion
          LPC_PWM1->MR5 = impulsion;
          LPC_PWM1->MR6 = impulsion; //*25000;  // *25000 si imulsion en [ms]
          LPC_PWM1->LER |= (1<<6);
		 }
		i++;
		if ( i > 1000000)
		{
			i = 0;
			printf("Attente nouvelle valeur d'impulsion par UDP...\n");
		}
	}

	// STOP PWM
	//LPC_PWM1->PCR = 0;
	//LPC_PWM1->TCR = 0;

    // PINSEL Pin Selection Function (PINSEL0 -> PINSEL9)
    // 00 = Primary Function, typically GPIO (reset default)
    // 01 = First Alternate Function.
    // 01 = Second Alternate Function.
    // 01 = Third Alternate Function.

    // LPC_PINCON Pin Connect Block dans LPC17xx.h
    LPC_PINCON->PINSEL0 &= (!0x00003000); // b11000000000000 si !
    printf("PINSEL0 = %d\n", (!0x00003000));

     // p.122
     // IO Port Direction Control Register -> direction of each Pin
     // 1 for OUTPUT, 0 for INPUT
     LPC_GPIO0->FIODIR = 0xffffffff;

     // (Fast)MASK Register for Port. Writes, Sets, Clears and Reads to Port
     // via FIOPIN, FIOSET and FIOCLR
     // ALTER or RETURN ONLY THE BITS ENABLED BY ZEROS IN THIS REGISTER
  	 LPC_GPIO0->FIOMASK = 0x00000000;  // si 0xffffffff, aucune pin n'est modifiee par SET ou CLR

    while (1)
    {

        // (Fast)PORT PIN Value Register, Current State of Digital Port Pins is read from this
    	// Register Regardless of Pin Direction or alternate function (except ADC input)
    	// !! The Value Read is MASKED and ANDing with INVERTED FIOMASK.
    	// Writing to this register places corresponding values in all bits enabled by Zeros in FIOMASK
    	//LPC_GPIO0->FIOPIN;

       // (Fast)CLEAR Register using FIOMASK -> writing 1s produces LOW at corresponding Pin
       // 1. ! Only Bits enabled by 0 in FIOMASK can be altered !
       // 2. ! WRITING 0s HAS NO EFFECT !
       LPC_GPIO0->FIOCLR = LED;
       printf("#%d OFF\n", count); // ! semihosting project
        	for (i = 0; i < DELAY; i++) ;

       // (Fast)SET Register using FIOMASK -> writing 1s produces HIGH at corresponding Pin
       // 1. ! Only Bits enabled by 0 in FIOMASK can be altered !
       // 2. Reading this Register return the current Contents of the Port Output Register
       // 3. ! WRITING 0s HAS NO EFFECT !
        LPC_GPIO0->FIOSET = LED;
        printf("#%d ON\n", count);  // ! semihosting project
        	for (i = 0; i < DELAY; i++) ;
      count++;
    }
    //while(1) ;
   return(0);
}

// Commande a envoyer au FB755AS
void mycallback(unsigned char* msg, short len, unsigned char broadcast)
{
//printf("IN CALL BACK !!!\n")

  msg[len] = '\0';
	printf("IMPULSION (chaine)=%s\n", msg);
	impulsion = atoi((const char*)msg);
	printf("IMPULSION (entier)=%d\n", impulsion);
	messageDispo = 1;
	//   UART1_SendCmd2FB755(msg);
}

void udpipActivity100MOn(void)
{
        printf("UDP 100M\n");
}

void udpipActivity10MOn(void)
{
        printf("UDP 10M\n");
}

void udpipActivityOff(void)
{
        printf("UDP OFF\n");
}

void UART1_IRQHandler(void)
{
  char car;
	//printf("UART1 INT!\n");  // ! semihosting project
	//LPC_UART1->IER &= ~(bit0); // Int Off -> ! alors plus d'interruption possible
	switch( (LPC_UART1->IIR & (bit1|bit2|bit3)) )   // Int Identification register
	{
	   case (bit1|bit2)	:	printf("RX line Status/Error\n");
	   	   	   	   	   	   	LPC_UART1->LSR;    // La lecture de LSR provoque Reset de l'interrupt
	   	   	   	   	   	   	// Todo, traiter le probleme
	   	   	   	   	   	    break;
	   case (bit2)		:	//printf("RX Data Available\n");
	   	   	   	   	   	    // LIRE RBR RESET L'INTERRUPT
	   	   	   	   	   	    car = LPC_UART1->RBR;
	   	   	   	   	   	   	//printf("Receive Buffer Register = [%c] ASCII=%d\n", car, (int)car);
	   	   	   				if ((car == 10) && (car_precedent == 13) && (debut_message == 0))
	   	   	   				{
	   	   	   					debut_message = 1;
	   	   	   					messageDispo = 0;
	   	   	   					car_precedent = car;
	   	   	   				}
	   	   	   				else if ((car == 10) && (car_precedent == 13) && (debut_message > 0))
	   	   	   	   	   	   	{
	   	   	   	   	   	   		*(message+(debut_message-2)) = '\0';
	   	   	   	   	   	   		messageDispo = 1;

	   	   	   	   	messageIndex = 0;debut_message = 0;
	   	   	   	   	   	   	}
	   	   	   	   	   	   	if ((debut_message >= 1) && (car != 10) && (car_precedent != 13))
	   	   	   	   	   	   	{
	   	   	   	   	   	   		*(message+(debut_message-1)) = car;
	   	   	   	   	   	   		debut_message++;
	   	   	   	   	   	   		messageDispo = 0;
	   	   	   	   	   	   	}
	   	   	   	   	   	   	car_precedent = car;
	   	   	   	   	   	   	break;
	   case (bit2|bit3)	:	printf("! UART CHARACTER TIMEOUT\n");
	   	   	    			// LIRE RBR RESET L'INTERRUPT
	   	   	   	   	   	    car = LPC_UART1->RBR;
	   	   	   	   	   	    // force termine message
	   	   	   	   	   	   	break;
	   case (bit1)		:	printf("! UART THRE\n");
	   	   	   	   	   	   	LPC_UART1->IIR; // La lecture de IIR provoque Reset de l'interrupt (deja dans le switch)
	   	   	   	   	   	   	// TODO
                            // .... ou write sur THR
	   	   	   	   	   	   	break;
	}
	//NVIC_ClearPendingIRQ(UART1_IRQn);
	//LPC_UART1->IER &= ~(bit0); // Int Off -> ! plus d'interruption possible
}
